﻿using System;
using System.Collections.Generic;

namespace MementoPattern;

// 联系人
public class ContactPerson
{
    public string Name { get; init; }
    public string MobileNum { get; init; }
}

// 发起人
public class MobileOwner(List<ContactPerson> persons)
{
    // 发起人需要保存的内部状态
    public List<ContactPerson> ContactPersons { get; private set; } = persons;

    // 创建备忘录，将当期要保存的联系人列表导入到备忘录中 
    public ContactMemento CreateMemento()
    {
        // 这里也应该传递深拷贝，new List方式传递的是浅拷贝，
        // 因为ContactPerson类中都是string类型,所以这里new list方式对ContactPerson对象执行了深拷贝
        // 如果ContactPerson包括非string的引用类型就会有问题，所以这里也应该用序列化传递深拷贝
        return new ContactMemento([..ContactPersons]);
    }

    // 将备忘录中的数据备份导入到联系人列表中
    public void RestoreMemento(ContactMemento memento)
    {
        // 下面这种方式是错误的，因为这样传递的是引用，
        // 则删除一次可以恢复，但恢复之后再删除的话就恢复不了.
        // 所以应该传递contactPersonBack的深拷贝，深拷贝可以使用序列化来完成
        this.ContactPersons = memento.ContactPersonBack;
    }

    public void Show()
    {
        Console.WriteLine("联系人列表中有{0}个人，他们是:", ContactPersons.Count);
        foreach (var p in ContactPersons)
        {
            Console.WriteLine("姓名: {0} 号码为: {1}", p.Name, p.MobileNum);
        }
    }
}

// 备忘录
public class ContactMemento(List<ContactPerson> persons)
{
    // 保存发起人的内部状态
    public readonly List<ContactPerson> ContactPersonBack = persons;
}

// 管理角色
public class Caretaker
{
    // 可以使用列表、链表、字典等数据结构实现多节点的备份:
    // https://www.cnblogs.com/zhili/p/MementoPattern.html
    public ContactMemento ContactM { get; init; }
}

public static class Program
{
    public static void Main()
    {
        List<ContactPerson> persons =
        [
            new ContactPerson { Name = "小王", MobileNum = "123445" },
            new ContactPerson { Name = "小张", MobileNum = "234565" },
            new ContactPerson { Name = "小李", MobileNum = "231455" }
        ];
        var mobileOwner = new MobileOwner(persons);
        mobileOwner.Show();

        // 创建备忘录并保存备忘录对象
        var caretaker = new Caretaker
        {
            ContactM = mobileOwner.CreateMemento()
        };

        // 更改发起人联系人列表
        Console.WriteLine("----移除最后一个联系人--------");
        mobileOwner.ContactPersons.RemoveAt(2);
        mobileOwner.Show();

        // 恢复到原始状态
        Console.WriteLine("-------恢复联系人列表------");
        mobileOwner.RestoreMemento(caretaker.ContactM);
        mobileOwner.Show();
    }
}